package vip.xiaomoli.courier.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import vip.xiaomoli.courier.component.timewheel.CourierTask;
import vip.xiaomoli.courier.component.timewheel.CourierTimeWheel;
import vip.xiaomoli.courier.dao.CourierDao;
import vip.xiaomoli.courier.model.TaskInfo;
import vip.xiaomoli.courier.util.CourierConstant;
import vip.xiaomoli.courier.util.CourierUtil;

import java.util.Date;

@Aspect
@Component
public class CourierAspect {

    @Autowired
    private CourierDao dao;

    @Autowired
    private CourierTimeWheel timeWheel;

    @Pointcut("this(vip.xiaomoli.courier.service.Courier) && args(param, delaySeconds)")
    public void pointcutExecute(String param, int delaySeconds) {}

    @Around(value = "pointcutExecute(param, delaySeconds)")
    public Object around(ProceedingJoinPoint joinPoint, String param, int delaySeconds) throws Throwable {
        if (Thread.currentThread().getName().startsWith(CourierConstant.THREAD_NAME)) {
            return joinPoint.proceed();
        }

        boolean isLoad = delaySeconds < CourierConstant.ADVANCE_LOAD_SECONDS; // 如果延时时间<提前加载时间，则直接放入时间轮执行

        TaskInfo ti = new TaskInfo();
        ti.setCourierName(joinPoint.getTarget().getClass().getName());
        ti.setParam(param);
        ti.setExecTime(CourierUtil.addSeconds(new Date(), delaySeconds));
        if (isLoad) {
            ti.setLoadFlag(1);
            ti.setLoadTime(new Date());
            ti.setExecServerIP(CourierUtil.getLocalIP());
        }
        long id = dao.insertTaskInfo(ti);

        if (isLoad) {
            ti.setId(id);
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    timeWheel.addTask(new CourierTask(ti, dao), delaySeconds);
                }
            });
        }
        return null;
    }

}
